﻿using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;

namespace MaterialTypeRecognition.Shell.Utils
{
    /// <summary>
    /// 窗口托盘类型。
    /// </summary>
    public static class WindowNotifyIcon
    {
        private const int WM_SYSCOMMAND = 0x0112;
        private const int SC_MINIMIZE = 0xF020;
        private const int WM_LBUTTONUP = 0x0202;

        [DllImport("user32.dll")]
        private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll")]
        private static extern IntPtr FindWindow(string className, string windowTitle);

        [DllImport("shell32.dll")]
        private static extern IntPtr Shell_NotifyIcon(int message, ref NOTIFYICONDATA pnid);

        private static IntPtr _notifyIconHandle;

        private static NOTIFYICONDATA _notifyIcomData;

        #region Win32 API 数据结构和常量

        private const int NIF_MESSAGE = 0x00000001;
        private const int NIF_ICON = 0x00000002;
        private const int NIF_TIP = 0x00000004;
        private const int WM_USER = 0x0400;
        private const int NIM_ADD = 0x00000000;
        private const int NIM_MODIFY = 0x00000001;
        private const int NIM_DELETE = 0x00000002;

        [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
        private struct NOTIFYICONDATA
        {
            public int cbSize;
            public IntPtr hWnd;
            public int uID;
            public int uFlags;
            public int uCallbackMessage;
            public IntPtr hIcon;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
            public string szTip;
        };
        #endregion

        private static Window _targetWindow = null!;

        private static System.Drawing.Icon _notifyIcon = null!;

        public static void AttachToWindow(Window targetWindow, Icon notifyIcon)
        {
            _notifyIcon = notifyIcon;
            _targetWindow = targetWindow;

            if (_targetWindow.IsLoaded)
            {
                InitNotifyIcon();
            }
            else
            {
                _targetWindow.Loaded += (s, e) =>
                {
                    InitNotifyIcon();
                };
            }
        }

        private static void InitNotifyIcon()
        {
            _targetWindow.StateChanged += OnWindowStateChanged;

            // 将窗口句柄赋给 _notifyIconHandle
            IntPtr mainWindowHandle = new WindowInteropHelper(_targetWindow).Handle;
            _notifyIconHandle = mainWindowHandle;
            // 创建通知区域图标
            _notifyIcomData = new NOTIFYICONDATA
            {
                cbSize = Marshal.SizeOf(typeof(NOTIFYICONDATA)),
                hWnd = _notifyIconHandle,
                uID = 1,
                uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP,
                uCallbackMessage = WM_USER + 1,
                hIcon = _notifyIcon.Handle
            };
            _notifyIcomData.szTip = _targetWindow.Title;

            // 注册托盘图标的回调消息
            HwndSource source = HwndSource.FromHwnd(_notifyIconHandle);
            source.AddHook(new HwndSourceHook(WndProc));
        }

        private static void OnWindowStateChanged(object? sender, EventArgs e)
        {
            if (_targetWindow.WindowState == WindowState.Minimized)
            {
                // 最小化到系统托盘
                _targetWindow.Hide();
                ShowNotifyIcon();
            }
        }

        private static IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            if (msg == WM_USER + 1)
            {
                if (lParam.ToInt32() == WM_LBUTTONUP)
                {
                    // 单击了托盘图标，显示主窗口
                    _targetWindow.Show();
                    _targetWindow.WindowState = WindowState.Normal;
                    _targetWindow.Activate();
                    RemoveNotifyIcon();
                }
            }

            return IntPtr.Zero;
        }

        private static void RemoveNotifyIcon()
        {
            var temp = new NOTIFYICONDATA
            {
                hWnd = _notifyIconHandle,
                uID = 1
            };

            // 移除通知区域图标
            Shell_NotifyIcon(NIM_DELETE, ref temp);
        }

        private static void ShowNotifyIcon()
        {
            // 将通知区域图标添加到系统托盘
            Shell_NotifyIcon(NIM_ADD, ref _notifyIcomData);
        }
    }
}